home *** CD-ROM | disk | FTP | other *** search
- /*
- * ***************
- * * X R F M . C *
- * ***************
- *
- * disk storage routines. To handle large concatanations, when
- * memory is full, it is necessary to write storage to disk each
- * time, and then take this into account when printing. In effect
- * XRF becomes a primitive polyphase sort.
- *
- * Version V1.17 1-Apr-85 MC first edition
- * Version V1.18 14-Apr-85 MC Packed records for workfiles
- *
- * The key is structured as <KEYactualNNNNNNNN> from XRF0.C where:-
- * KEY is the symbol as lower case
- * length CPS characters.
- * actual is the symbol as she appears
- * length CPS characters.
- * NNNNNNNN is the program name
- * length 8 chars
- * Carried with this is the Reference as an integer.
- *
- * version V1.19 25-Apr-85 MC Use path picked up as from C86TEMP
- * which is loaded as SET C86TEMP=
- * The most sensible use of this is
- * ramdrive.
- */
-
-
- #include <stdio.h>
- #include "xrf.h"
-
- static struct BUFR wbuf; /* static buffer as this is for mem full pb */
- /*----------------------------------------------------------------*/
- /* write tree. Write memory structure to disk, sorted records so */
- /* merge phase can just collate */
- /* Record structure is:- */
- /* 2 byte record count as int */
- /* n byte key 1 as ASCIIZ (max CPS+1) */
- /* n byte key 1 as ASCIIZ (max CPS+1) */
- /* n byte key 1 as ASCIIZ (max 8+1) */
- /* 2 byte reference number as int */
- /* */
- /* The node is now positioned in the tree in case non-sensitive order.
- * This means that in the final list mixed, upper & lower case symbols
- * appear togethor instead of being separated in the collating sequence.
- *
- */
- wrtree(ofile,link)
- struct dsk *ofile;
- struct idt *link;
-
- { struct ref *r; /* Ref chain pointer */
- int ks=2; /* size of key */
- if (link != NULL){
- wrtree(ofile,link->left); /* Visit the left */
- ks+=wpack(ofile->mdnbuf->b_key,link->keyp); /* insert key into buffer */
- for(r=link->first;r!=NULL;r=r->next){ /* process ref chain */
- wrput(ofile->mdnfile,&ks,2); /* Write reclen bytes */
- wrput(ofile->mdnfile,ofile->mdnbuf->b_key,ks-2);
- wrput(ofile->mdnfile,&r->lno,2); /* Write ref for this one */
- ofile->mdncnt++;
- }
- wrtree(ofile,link->right); /* Visit the right */
- }
- }
- struct dsk *wropen(seqno) /* open next memory write file */
- int seqno; /* sequence number */
- { struct dsk *w;
- char *malloc();
- if((w=(struct dsk *)malloc(sizeof(struct dsk)))==NULL)
- abort("WOPEN no memory\n");
- w->mdnprev=w->mdnnext=NULL;
- w->mdnbuf=&wbuf;
- w->mdneof=w->mdnempty=w->mdncnt=0;
- sprintf(w->mdnfname,"%sXREF%04d.$$$",wpath,seqno);
- if((w->mdnfile=fopen(w->mdnfname,"wb"))==NULL)
- abort("WOPEN can't create %s\n",w->mdnfname);
- return w;
- }
- wrfix() /* fix disk chain into place */
- { struct dsk *last=NULL, *this=polroot, *temp;
- char *malloc();
- int mcnt=0;
- while (this!=NULL){ /* scan list */
- if(this->mdnfile!=NULL)fclose(this->mdnfile);
- if(this->mdncnt){
- if((this->mdnbuf=(struct BUFR *)malloc(sizeof(struct BUFR)))==NULL)
- quit(); /* I give up *
- if((this->mdnfile=fopen(this->mdnfname,"rb"))==NULL)
- abort("WRFIX can't reopen %s\n",this->mdnfname);
- mcnt++;
- if(verbose)printf("WRFIX Process %s for %9d records\n",
- this->mdnfname,this->mdncnt);
- this->mdnempty=1; /* force 'buffer empty' */
- this->mdneof=0; /* not EOF */
- last=this;
- this=this->mdnnext; /* go to next */
- this->mdnprev=last; /* ( and tell it about this one) */
- }
- else { /* nought written, lose it */
- unlink(this->mdnfname);
- temp=this;
- if(last!=NULL)this=last->mdnnext=this->mdnnext;
- else this=polroot=this->mdnnext;
- free(temp);
- }
- }
- if(verbose)printf("WRFIX kept %1d memory files\n",mcnt);
- }
-
- wpack(nk,kp) /* pack kp->nk returning length in bytes */
- char *kp;
- char *nk;
- { char *tp=nk, *wpackey();
- tp=wpackey(tp,kp,CPS); /* key string 1*/
- tp=wpackey(tp,kp+CPS,CPS); /* key string 2*/
- tp=wpackey(tp,kp+CPS+CPS,8); /* key string 3*/
- return (int)(tp-nk);
- }
- char *wpackey(kp,k,len) /* lose trailing spaces on key, return count */
- char *kp; /* buffer to update */
- char k[]; /* input key */
- int len; /* max length of input key */
- { int i,stop;
- for(stop=len;stop;stop--)if(k[stop-1]!=' ')break;
- for(i=0;i<stop;*kp++=k[i++]);
- *kp++='\0';
- return kp;
- }
-
- wrput(f,cp,bytes)
- FILE *f;
- char *cp;
- int bytes;
- { int i;
- for(i=0;i<bytes;i++)
- if(fputc(*cp++,f)==EOF)abort("WRPUT Disk full!\n");
- }
-
- /*-------------------------------------------------------------------*/
- /* Merge phase - see if there is a lower key on a disk file compared */
- /* against the current in-core entry. */
- /* return NULL if not (memory table is Prime key) */
- struct BUFR *wrmatch(base,node,ref)
- struct dsk *base; /* file linked list base */
- struct idt *node; /* memory node */
- struct ref *ref;
- { struct dsk *fptr=base, *lowest=NULL;
- int cf, flag=0;
- strcpy(wbuf.b_key,noe->keyp); /* make memory key in buffer */
- wbuf.b_ref=ref->lno;
- lowest=&wbuf;
- while (fptr!=NULL){ /* check if lower on disk */
- if(fptr->mdnempty)wget(fptr);
- if(!fptr->mdneof){
- if((cf=strcmp(fptr->mdnbuf->b_key,lowest->b_key))<0){
- flag++;
- lowest=fptr; /* lowest key */
- }
- else if(cf==0&&fptr->mdnbuf->b_ref<lowest->b_ref){
- flag++;
- lowest=fptr; /* lowest ref on equal keys */
- }
- }
- fptr=fptr->mdnnext;
- }
- if(flag){
- lowest->mdnempty=1;
- return (lowest->mdnbuf);
- }
- return NULL;
- }
- wget(fptr) /* get next record & expand */
- struct dsk *fptr;
- { int reclen;
- char recin[KEYSIZE+2+1]; /* input packed disk record
- if(fptr->mdneof)return;
- fptr->mdnempty=0; /* buffer flagged as filled in case EOF*/
- if(wgetr(fptr,&reclen,2)==EOF)return; /* get reclen */
- if(wgetr(fptr,recin,reclen)==EOF)return; /* get record */
- wunpack(fptr->mdnbuf,recin);
- }
-
- wgetr(fptr,buf,len) /* read <len> bytes into <buf> */
- struct dsk *fptr;
- unsigned char *buf;
- int len;
- { int j;
- while(len--){
- if((j=fgetc(fptr->mdnfile))==EOF){
- fptr->mdneof=1;
- return j;
- }
- *buf++=j;
- }
- }
-
- wunpack(nk,ok) /* get packed key as struct BUFR */
- struct BUFR *nk; /* return EOF if file end */
- char *ok;
- { char *wunpackey(), *kp=&nk->b_key;
- ok=wunpackey(ok,kp,CPS); /* key 1*/
- ok=wunpackey(ok,kp+CPS,CPS); /* key 2*/
- ok=wunpackey(ok,kp+CPS+CPS,8); /* key 3 (EOS will be there) */
- kp=&nk->b_ref; /* get reference */
- *kp++=*ok++;
- *kp++=*ok++;
- return (0);
- }
-
- char *wunpackey(kp,k,len) /* convert key string->fixed length*/
- char *kp; /* buffer in */
- char k[]; /* new key */
- int len; /* max length of key */
- { int i=0;
- while(*kp)k[i++]=*kp++; /* move in key */
- while(i<len)k[i++]=' '; /* pad with spaces to size */
- k[i]='\0'; /* mark end of key (in case last one) */
- return ++kp;
- }
- wrkill() /* kill disk chain */
- struct dsk *last=NULL, *this=polroot, *temp;
- while (this!=NULL){ /* scan list */
- fclose(this->mdnfile);
- unlink(this->mdnfname);
- temp=this;
- this=this->mdnnext;
- free(temp);
- }
- polcurr=polroot=NULL;
- }
- #ifdef DEBUG
- wtrace(tn,dptr)
- char *tn;
- struct dsk *dptr;
- { printf("%s node [%04x] F %04x %s C %4d Pr %04x Nx %04x Sw %1d %1d %04x\n",
- tn,dptr,
- dptr->mdnfile,dptr->mdnfname,dptr->mdncnt,dptr->mdnprev,
- dptr->mdnnext,dptr->mdnempty,dptr->mdneof,dptr->mdnbuf);
- }
- #endif